home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Applications / Communication / NewsBase / Source / INewsBase.m < prev    next >
Text File  |  1993-01-12  |  21KB  |  715 lines

  1. /*$Copyright:
  2.  * Copyright (C) 1992.5.22. Recruit Co.,Ltd. 
  3.  * Institute for Supercomputing Research
  4.  * All rights reserved.
  5.  * NewsBase  by ISR, Kazuto MIYAI, Gary ARAKAKI, Katsunori SUZUKI, Kok-meng Lue
  6.  *
  7.  * You may freely copy, distribute and reuse the code in this program under 
  8.  * following conditions.
  9.  * - to include this notice in the source code, if it is to be distributed 
  10.  *   with source code.
  11.  * - to add the file named "COPYING" within the code, which shall include 
  12.  *   GNU GENERAL PUBLIC LICENSE(*).
  13.  * - to display an acknowledgement in binary code as follows: "This product
  14.  *   includes software developed by Recruit Co.,Ltd., ISR."
  15.  * - to display a notice which shall state that the users may freely copy,
  16.  *   distribute and reuse the code in this program under GNU GENERAL PUBLIC
  17.  *   LICENSE(*)
  18.  * - to indicate the way to access the copy of GNU GENERAL PUBLIC LICENSE(*)
  19.  *
  20.  *   (*)GNU GENERAL PUBLIC LICENSE is stored in the file named COPYING
  21.  * 
  22.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  23.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  24.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  25. $*/
  26. #import "INewsBase.h"
  27. #import "INntpIO.h"
  28. #import "IDataGroupBrowser.h"
  29. #import "IItemHeaderBrowser.h"
  30. #import "INXBrowserCellWithLinkedObject.h"
  31. #import "INewsgroupInfoD.h"
  32. #import "IUifNode.h"
  33. #import "SideSplitView.h"
  34. #import "IBaseControl.h"
  35. #import "IFolderDockMatrix.h"
  36. #import "data_types.h"
  37. #import <appkit/appkit.h>
  38. #import <stdio.h>
  39. #import <string.h>
  40. #import <mach/mach.h>
  41. #import <defaults/defaults.h>
  42. #import "data_types.h"
  43. #import "errdebug.h"
  44. #import "Localization.h"
  45.  
  46. #define LoStr(key)      doLocalString(NULL,key,NULL)
  47.  
  48.  
  49. //#define         NNTPHOST        "isrgwy"
  50.  
  51.  
  52. @implementation INewsBase
  53.  
  54. + (char *)label
  55. {
  56.     return ("NewsBase...");
  57. }
  58.  
  59. - init
  60. {
  61.     BrowserMode        newsgroupMode, articleMode;
  62.     id             loadingAlertPanel;
  63.     NXModalSession     loadingModalSession;
  64.  
  65.     [super init];
  66.     iNntpIO = nil;
  67.  
  68.     /* make zone for NewsBase */
  69.     newsbaseZone = NXCreateZone (vm_page_size, vm_page_size, YES);
  70.     /* load window into screen */
  71.     LoadLocalNib("NewsBase.nib",self,NO,newsbaseZone);
  72. /*
  73.     [NXApp loadNibSection:"NewsBase.nib" owner:self 
  74.                     withNames:NO fromZone:(NXZone *)newsbaseZone];
  75. */
  76.     /* open openNewsBasePanel */
  77.     if ([self openNewsBasePanel] == 0) {
  78.     /* click cancel */
  79.         [NXApp delayedFree:self];
  80.     return(nil);
  81.     } 
  82.     /* click OK */
  83.     /* read default database for newsgroupMode & articleMode */
  84.     if (strcmp(NXGetDefaultValue(OWNER, NEWSGROUPBROWSERMODE),"List")==0) {
  85.     newsgroupMode = Flat;
  86.     } else {
  87.     newsgroupMode = Tree;
  88.     }
  89.     if (strcmp(NXGetDefaultValue(OWNER, ARTICLEBROWSERMODE),"ByReference")
  90.         == 0) {
  91.     articleMode = Tree;
  92.     } else if (strcmp(NXGetDefaultValue(OWNER, ARTICLEBROWSERMODE),"BySubject")
  93.         == 0) {
  94.     articleMode = BySubject;
  95.     } else if (strcmp(NXGetDefaultValue(OWNER, ARTICLEBROWSERMODE),"ByKeyword")
  96.         == 0) {
  97.     articleMode = ByKeyword;
  98.     } else {
  99.     articleMode = Flat;
  100.     }
  101.     [iNntpIO setArticleMode:articleMode];
  102.  
  103.     /* open connection to nntp server */
  104.     loadingAlertPanel = NXGetAlertPanel(LoStr("NewsBase"), 
  105.     LoStr("Connecting to nntp server..., please wait"),
  106.     NULL, NULL, NULL);
  107.     [NXApp beginModalSession:&loadingModalSession for:loadingAlertPanel];
  108.  
  109.     iNntpIO = [[INntpIO allocFromZone:newsbaseZone] 
  110.                      initServer:iNntpHost allNews:iAllNewsFlag
  111.                 newsGroupMode:(BrowserMode)newsgroupMode
  112.                 articleMode:(BrowserMode)articleMode];
  113.     if (iNntpIO==nil) {
  114.     /* failed to connect to server */
  115.     /* stop modal loop */
  116.     [NXApp endModalSession:&loadingModalSession];
  117.     [loadingAlertPanel orderOut:self];
  118.     NXFreeAlertPanel(loadingAlertPanel);
  119.     /* free objects */
  120.     [oNewsReader free];
  121. //    [oViewControlPanel free];
  122.     [iNntpIO free];
  123.     [super free];
  124.     return nil;
  125.     }
  126.  
  127.     [NXApp endModalSession:&loadingModalSession];
  128.     [loadingAlertPanel orderOut:self];
  129.     NXFreeAlertPanel(loadingAlertPanel);
  130.  
  131.     // set hierarchy of view and size from user's default data base
  132.     [self _readWindowInfoFromDefaultDBandSetupViews];
  133.     
  134.     /* make NewsBase window */
  135.     [self _setUpInterfaceWindow];
  136.  
  137.     return self;
  138. }
  139.  
  140. - _readWindowInfoFromDefaultDBandSetupViews
  141. {
  142.     const char *buffer;
  143.     NXRect     newsbaseRect;
  144.     NXSize folderDockSize, browserSplitViewSize, leftSideSize, rightSideSize;
  145.     NXRect    frameRect;
  146.  
  147.     /* setup for side spilited view, newsgroup browser and article browser */
  148.     [oNewsgroupView setAutoresizeSubviews:YES];
  149.     [oNewsgroupView addSubview:oNewsfolderScroll];
  150.     [oNewsgroupView addSubview:oNewsGroupNXBrowser];
  151.     
  152.     if ((buffer = NXGetDefaultValue(OWNER, NNTPBROWSER_FRAME)) != 0 &&
  153.         sscanf(buffer, "(%f,%f):(%f,%f):(%f,%f):(%f,%f):(%f,%f):(%f,%f)", 
  154.         &newsbaseRect.origin.x,&newsbaseRect.origin.y,
  155.         &newsbaseRect.size.width, &newsbaseRect.size.height,
  156.         &folderDockSize.width, &folderDockSize.height,
  157.         &browserSplitViewSize.width, &browserSplitViewSize.height,
  158.         &leftSideSize.width, &leftSideSize.height,
  159.         &rightSideSize.width, &rightSideSize.height
  160.     ) == 12) {
  161.         [oNewsReader placeWindow:&newsbaseRect];
  162.         [oNewsgroupView sizeTo:leftSideSize.width :leftSideSize.height];
  163.     [oArticleNXBrowser sizeTo:rightSideSize.width :rightSideSize.height];
  164.     [oNewsfolderDock sizeTo:folderDockSize.width :folderDockSize.height];
  165.     [oNewsfolderDockMatrix sizeTo:folderDockSize.width :folderDockSize.height];
  166.     [oBrowserSplitView sizeTo:browserSplitViewSize.width
  167.                  :browserSplitViewSize.height];
  168.     }
  169.     
  170.     /* setup side split view */
  171.     [oBrowserSplitView setRightView:oArticleNXBrowser];
  172.     [oBrowserSplitView setLeftView:oNewsgroupView];
  173.  
  174.     /* setup for newsgroup folder dock and bowser */
  175.     [oSplitView addSubview:oNewsfolderDock];
  176.     [oSplitView addSubview:oBrowserSplitView];
  177.     [oBrowserSplitView initViews];
  178.  
  179.     [oNewsfolderScroll setAutoresizeSubviews:YES];
  180.     
  181.  
  182. //    [oNewsfolderScrollMatrix notifyAncestorWhenFrameChanged:YES];
  183.     
  184.     [oNewsfolderScrollMatrix getFrame:&frameRect];
  185.     frameRect.origin.x = frameRect.origin.y = 0.0;
  186.     [oNewsfolderScrollMatrix setFrame:&frameRect];
  187.  
  188.     [oNewsfolderScrollDocView getFrame:&frameRect];
  189.     frameRect.origin.x = frameRect.origin.y = 0.0;
  190.     [oNewsfolderScrollDocView setFrame:&frameRect];
  191.  
  192.     [oNewsfolderScrollDocView addSubview:oNewsfolderScrollMatrix];
  193.     [oNewsfolderScrollDocView setAutoresizeSubviews:NO];
  194.     [oNewsfolderScroll setDocView:oNewsfolderScrollDocView];
  195.     
  196.     // set delegate for resizing behavior when sliding divider bar
  197. //    [oSplitView setDelegate:oNewsfolderDockMatrix];
  198.     [oSplitView setDelegate:self];
  199.  
  200.     // set root cell (next station icon) for newsgroup folder view
  201.     // oNewsfolderScroll is scroll view, 
  202.     // which document view is IFolderScrollMatrix
  203.     [oNewsfolderScrollMatrix setRootName:[iNntpIO rootName]];
  204.     [oNewsfolderDockMatrix setRootName:[iNntpIO rootName]];
  205.  
  206.     [[oNewsReader contentView] displayFromOpaqueAncestor:NULL :0 :YES];
  207.     
  208.     [oNewsfolderDockMatrix registerCells];
  209.     
  210.     return self;
  211. }
  212.  
  213. - _setUpInterfaceWindow
  214. {
  215.     /*
  216.      * The objects in this module are:
  217.      *     INewsBase initializes the module.
  218.      *     NewsGroupTree holds the newsgroups in a tree structure.
  219.      *     NewsGroupTreeControl initializes and maintains the NewsGroupTree.
  220.      */
  221.      
  222.     /* set up news group browser */
  223.     [oNewsGroupNXBrowser setIOmodule:iNntpIO];
  224.     if ([iNntpIO newsGroupMode]==Flat) {
  225.     [oNewsGroupNXBrowser setMaxVisibleColumns:1];
  226.     } else {
  227.     [oNewsGroupNXBrowser setMaxVisibleColumns:4];
  228.     }
  229.  
  230.     /* set up article browser */
  231.     [oArticleNXBrowser setIOmodule:iNntpIO];
  232.     if ([iNntpIO articleMode]==Flat) {
  233.     [oArticleNXBrowser setMaxVisibleColumns:1];
  234.     } else {
  235.     [oArticleNXBrowser setMaxVisibleColumns:2];
  236.     }
  237.  
  238.     /* load cell into NewsGroupBrowser */
  239.     [oNewsGroupNXBrowser setRootListnode:[iNntpIO subDirectoryOf:nil]];
  240.     [oNewsGroupNXBrowser loadColumnZero];
  241.  
  242.     /* set up interaction of DataGroupBrowser,ItemRepBrowser,ItemBrowser */
  243.     [oNewsGroupNXBrowser setItemRepUIF:oArticleNXBrowser];
  244.     [oArticleNXBrowser setDataGroupUIF:oNewsGroupNXBrowser];
  245.  
  246.     /* set control panel */
  247.     [oNewsReader setDelegate:self];
  248.     
  249.     [self setArticleBrowserMode];
  250.  
  251.     /* set up window for getting article number */
  252.     [iNntpIO setOGetArticleNumWindow:oGetArticleNumWindow];
  253.     [iNntpIO setOGetArticleNumField:oGetArticleNumField];
  254.     [iNntpIO setIPercentageView:oPercentageView];
  255.     
  256.     [oArticleNumOKButton setTarget:iNntpIO];
  257.     [oArticleNumCancelButton setTarget:iNntpIO];
  258.     [oArticleNumOKButton setAction:@selector(okArticleNumWindow:)];
  259.     [oArticleNumCancelButton setAction:@selector(cancelArticleNumWindow:)];
  260.  
  261.     DBG(10, fprintf(stderr," NewsBase is made\n"));
  262.        
  263.     return self;
  264. }
  265.  
  266. - (char *)label
  267. {
  268.     static char    labelString[64];
  269.     
  270.     sprintf (labelString, "NewsBase: %.53s", iNntpHost);
  271.     return labelString;
  272. }
  273.  
  274. - show:sender
  275. {
  276.     unsigned int windowNum;
  277.     NXRect    oldRect;
  278.  
  279.     [oNewsReader display];
  280.     [oNewsReader makeKeyAndOrderFront:self];
  281.     // register window for accepting file icons
  282.     NXConvertWinNumToGlobal([oNewsReader windowNum], &windowNum);
  283.     [[NXApp appSpeaker] setSendPort:NXPortFromName(NX_WORKSPACEREQUEST, NULL)];
  284.     [[NXApp appSpeaker] registerWindow:windowNum
  285.         toPort:[[NXApp appListener] listenPort]];
  286.  
  287.     // these statements should not be needed here. but
  288.     // I could not register rectangle of cells during setting up views
  289.     // in "_readWindowInfoFromDefaultDBandSetupViews" above.
  290.     [oNewsfolderDockMatrix registerCells];
  291.     [oNewsfolderScrollMatrix registerCells];
  292.     [oSplitView getFrame:&oldRect];
  293.     [self splitView:oSplitView 
  294.                 resizeSubviews:(const NXSize *)&(oldRect.size)];
  295.     
  296.     return(self);
  297. }
  298.  
  299. - terminateProc
  300. {
  301.     [self _saveWindowInfoToDefaultDB];
  302.     return self;
  303. }
  304.  
  305. - (BOOL)postArticle:(const char *)article length:(int)length
  306. {
  307.     return([iNntpIO postArticle:article length:length]);
  308. }
  309.  
  310. - (BOOL)sendArticle:(const char *)messageId
  311. {
  312.     return([iNntpIO sendArticle:messageId]);
  313. }
  314.  
  315. - newsGroupTreeControl
  316. {
  317.     return iNntpIO;
  318. }
  319.  
  320. - toggleNewsGroupBrowser:sender
  321. {
  322.     if ([iNntpIO toggleNewsGroupMode:sender]==Flat) {
  323.     [oNewsGroupNXBrowser setMaxVisibleColumns:1];
  324.         NXWriteDefault(OWNER, NEWSGROUPBROWSERMODE, "List");
  325.     } else {
  326.     [oNewsGroupNXBrowser setMaxVisibleColumns:4];
  327.         NXWriteDefault(OWNER, NEWSGROUPBROWSERMODE, "Browser");
  328.     }
  329.     /* reset newsgroup browser and redraw new browser */
  330.     [oNewsGroupNXBrowser setRootListnode:[iNntpIO subDirectoryOf:nil]];
  331.     [oNewsGroupNXBrowser loadColumnZero];
  332.     return self;
  333. }
  334.  
  335. - toggleArticleBrowser:sender
  336. {
  337.     [iNntpIO toggleArticleMode:sender];
  338.     [self setArticleBrowserMode];
  339.     return(self);
  340. }
  341.  
  342. - setArticleBrowserMode
  343. {
  344.     id        node;
  345.     id        itemHeaderslist;
  346.     
  347.     switch ([iNntpIO articleMode]) {
  348.     case Flat:
  349.         [oArticleNXBrowser setMaxVisibleColumns:1];
  350.     [oArticleNXBrowser setTitle:LISTCOL0TITLE ofColumn:0];
  351.         NXWriteDefault(OWNER, ARTICLEBROWSERMODE, "List");
  352.         break;
  353.     case Tree:
  354.     [oArticleNXBrowser setMaxVisibleColumns:2];
  355.     [oArticleNXBrowser setTitle:BROWSERCOL0TITLE ofColumn:0];
  356.         NXWriteDefault(OWNER, ARTICLEBROWSERMODE, "ByReference");
  357.         break;
  358.     case BySubject:
  359.         [oArticleNXBrowser setMaxVisibleColumns:2];
  360.     [oArticleNXBrowser setTitle:SUBJECTCOL0TITLE ofColumn:0];
  361.         NXWriteDefault(OWNER, ARTICLEBROWSERMODE, "BySubject");
  362.         break;
  363.     case ByKeyword:
  364.     [oArticleNXBrowser setTitle:KEYWORDCOL0TITLE ofColumn:0];
  365.         [oArticleNXBrowser setMaxVisibleColumns:2];
  366.         NXWriteDefault(OWNER, ARTICLEBROWSERMODE, "ByKeyword");
  367.         break;
  368.     }
  369.     /* reset article browser */
  370.     node = [self _nodeForSelectedCellInBrowser:oNewsGroupNXBrowser];
  371.     itemHeaderslist = [iNntpIO itemHeadersOf:node];
  372.  
  373.     /* update article browser */
  374.     [oArticleNXBrowser setRootListnode:itemHeaderslist];
  375.     [oArticleNXBrowser loadColumnZero];
  376.     return(self);
  377. }
  378.  
  379. - setReadFlagToAll:sender
  380. {
  381.     id        node;
  382.     id        itemHeaderslist;
  383.  
  384.     [iNntpIO setReadFlag:(ReadFlag)ALL];
  385.     node = [self _nodeForSelectedCellInBrowser:oNewsGroupNXBrowser];
  386.     itemHeaderslist = [iNntpIO itemHeadersOf:node];
  387.  
  388.     /* update article browser */
  389.     [oArticleNXBrowser setRootListnode:itemHeaderslist];
  390.     [oArticleNXBrowser loadColumnZero];
  391.  
  392.     /* set read flag to default */
  393.     [iNntpIO setReadFlag:(ReadFlag)UNMARKEDONLY];    
  394.     return self;
  395. }
  396.  
  397. - markAllArticleAsRead:sender
  398. {
  399.     id        lastColumnMatrix;
  400.     
  401.     switch(NXRunAlertPanel(LoStr("NewsBase"),
  402.     LoStr("Cannot Undo! all article will be marked as read."),
  403.     LoStr("OK"),LoStr("Cancel"),NULL)) {
  404.         case NX_ALERTDEFAULT:
  405.         lastColumnMatrix = [oNewsGroupNXBrowser matrixInColumn:
  406.                         [oNewsGroupNXBrowser lastColumn]];
  407.         [lastColumnMatrix sendAction:@selector(markAllArticleOfCell:)
  408.                                  to:self forAllCells:NO];
  409.             break;
  410.         case NX_ALERTALTERNATE:
  411.             return(self);
  412.     }
  413.     /* reset article browser */
  414.     [oArticleNXBrowser setRootListnode:nil];
  415.     [oArticleNXBrowser loadColumnZero];
  416.     return self;
  417. }
  418.  
  419. - markAllArticleOfCell:sender
  420. {
  421.     /* this method will be called from oNewsGroupNXBrowser's cell */
  422.     /* "markAllArticleAsRead:" will triger it */
  423.     id        newsGroup;
  424.     id        groupInfo;
  425.     
  426.     newsGroup = [[sender node] linkedData];
  427.     groupInfo = [newsGroup dataForKey:GROUPINFO];
  428.     
  429.     [groupInfo markAllArticle];
  430.     return self;
  431. }
  432.  
  433. - getNewArticles:sender
  434. {
  435.     if ([iNntpIO reconnectServer:sender] == nil) {
  436.     NXRunAlertPanel(LoStr("NewsBase"),
  437.         LoStr("Can not recconect to nntp server."), LoStr("OK"),NULL,NULL);
  438.     [NXApp terminate:self];
  439.     }
  440.     [oArticleNXBrowser setRootListnode:nil];
  441.     [oArticleNXBrowser loadColumnZero];
  442.  
  443.     return self;
  444. }
  445.  
  446. - unSubscribeGroup:sender
  447. {
  448.     id        lastColumnMatrix;
  449.  
  450.     switch(NXRunAlertPanel(LoStr("NewsBase"),
  451.     LoStr("Cannot Undo! Selected newsgroup in browser will be unsubscribed."),
  452.     LoStr("OK"),LoStr("Cancel"),NULL)) {
  453.         case NX_ALERTDEFAULT:
  454.         lastColumnMatrix = [oNewsGroupNXBrowser matrixInColumn:
  455.                         [oNewsGroupNXBrowser lastColumn]];
  456.         [lastColumnMatrix sendAction:@selector(unSubscribeGroupOfCell:)
  457.                                  to:self forAllCells:NO];
  458.         /* reset oNewsGroupNXBrowser browser */
  459.         [lastColumnMatrix display];
  460.             break;
  461.         case NX_ALERTALTERNATE:
  462.             break;
  463.     }
  464.     return (self);
  465. }
  466.  
  467. - unSubscribeGroupOfCell:sender
  468. {
  469.     /* this method will be called from oNewsGroupNXBrowser's cell */
  470.     /* "unSubscribeGroup:" will triger it */
  471.     id        node;
  472.     id        groupInfo;
  473.     
  474.     node = [sender node];
  475.     groupInfo = [[node linkedData] dataForKey:GROUPINFO];
  476.     
  477.     [groupInfo addInfoString:"no" key:SUBSCRIBE];
  478.     [node setActive:NO];
  479.     [sender setActive:NO];
  480.     
  481.     return self;
  482. }
  483.    
  484. - _nodeForSelectedCellInBrowser:kbrowser
  485. {
  486.     id        lastColumnMatrix;
  487.     id        selectedCell;
  488.  
  489.     lastColumnMatrix = [kbrowser matrixInColumn:[kbrowser lastColumn]];
  490.     selectedCell = [lastColumnMatrix selectedCell];
  491.     
  492.     return [selectedCell node];
  493. }
  494.  
  495. - (int)openNewsBasePanel
  496. {
  497.     const char    *servername;
  498.     int returnCode;
  499.     
  500.     servername = NXGetDefaultValue(OWNER, NNTPSERVER);
  501.  
  502.     DBG(10,fprintf(stderr,"default value nntpserver=%s",servername));
  503.     [oOpenNewsBasePanel makeKeyAndOrderFront:self];
  504.     [oNntpServerNameField setStringValue:(char *)servername];
  505.  
  506.     returnCode = [NXApp runModalFor:oOpenNewsBasePanel];
  507.     [oOpenNewsBasePanel free];
  508.     return(returnCode);
  509. }
  510.  
  511. - cancelConnect:sender
  512. {
  513.     [NXApp stopModal:0];
  514.     return self;
  515. }
  516.  
  517. - okConnect:sender
  518. {
  519.     strncpy(iNntpHost, [oNntpServerNameField stringValue],
  520.                              (sizeof(iNntpHost)-1));
  521.     if ([[oGroupSelectionButton selectedCell] tag]==0) {
  522.     iAllNewsFlag = NO;
  523.     } else {
  524.     iAllNewsFlag = YES;
  525.     }
  526.     [NXApp stopModal:1];
  527.     return self;
  528. }
  529.     
  530. - windowDidBecomeKey:sender
  531. {
  532.     [[NXApp delegate] browserDidBecomeKey:self];
  533.     return(self);
  534. }
  535.  
  536. - windowDidResignKey:sender
  537. {
  538.     [[NXApp delegate] browserDidResignKey:self];
  539.     return(self);
  540. }
  541.  
  542. - windowWillClose:sender
  543. {
  544.     [self _saveWindowInfoToDefaultDB];
  545.     [[NXApp delegate] browserDidResignKey:self];
  546.     [NXApp delayedFree:self];
  547.     return(self);
  548. }
  549.  
  550. - _saveWindowInfoToDefaultDB
  551. {
  552.     NXRect newsbaseRect;
  553.     NXRect folderDockRect, browserViewRect, leftSideRect, rightSideRect;
  554.     char buffer[256];
  555.  
  556.     //   +----------------------+  -+
  557.     //   |    folderDock        |  newsbaseRect
  558.     //   +----------------------+   |
  559.     //   |        |             |   |
  560.     //   |leftSide|             |   |
  561.     //   |        |             |   |
  562.     //   +----------------------+  -+
  563.  
  564.     // save .newsrc file
  565.     [iNntpIO saveNewsRcFile];
  566.     // save .dir.newsbase file
  567.     [oNewsfolderDockMatrix saveDirFile];
  568.     
  569.     // save NewsBase frameSize and location of divider
  570.     [oNewsReader getFrame:&newsbaseRect];
  571.     [oNewsfolderDock getFrame:&folderDockRect];
  572.     [oBrowserSplitView getFrame:&browserViewRect];
  573.     [oNewsgroupView getFrame:&leftSideRect];
  574.     [oArticleNXBrowser getFrame:&rightSideRect];
  575.     
  576.     sprintf(buffer, "(%.0f,%.0f):(%.0f,%.0f):"
  577.             "(%.0f,%.0f):(%.0f,%.0f):(%.0f,%.0f):(%.0f,%.0f)", 
  578.         newsbaseRect.origin.x, newsbaseRect.origin.y,
  579.                newsbaseRect.size.width, newsbaseRect.size.height,
  580.             folderDockRect.size.width, folderDockRect.size.height,
  581.         browserViewRect.size.width, browserViewRect.size.height,
  582.               leftSideRect.size.width, leftSideRect.size.height,
  583.               rightSideRect.size.width, rightSideRect.size.height);
  584.     
  585.     NXWriteDefault(OWNER, NNTPBROWSER_FRAME, buffer);
  586.     return self;
  587. }
  588.  
  589. - free
  590. {
  591.     if (iNntpIO != nil) {
  592.         [iNntpIO saveNewsRcFile];
  593.         [iNntpIO free];
  594.     }
  595.     [oNewsReader free];
  596.     [oGetArticleNumWindow free];
  597.     [self perform:@selector(destroyZone:) with:nil afterDelay:1
  598.         cancelPrevious:NO];
  599.     return(nil);
  600. }
  601.  
  602. - destroyZone:dummy
  603. {
  604.     NXDestroyZone(newsbaseZone);
  605.     [super free];
  606.     return(nil);
  607. }
  608.  
  609. /* delegate method for NXSplitView */
  610.  
  611. #define        SCRLLMATRIX_HEIGHT    107  // height for oNewsfolderScroll
  612.  
  613. - splitView:sender resizeSubviews:(const NXSize *)oldSize
  614. {
  615.     id        upperView, lowerView;
  616.     NXRect    viewFrame, upperFrame;
  617.     int        ncols, nrows;
  618.     int        i, j;
  619.     NXSize    cellSize, intercell;
  620.     int        numRows, numCols;
  621.     
  622.     DBG(1,fprintf(stderr,"-- splitView:\n"));
  623. //    upperView = *(NX_ADDRESS([sender subviews]));
  624. //    lowerView = *(NX_ADDRESS([sender subviews]) + 1);
  625.     upperView = oNewsfolderDock;
  626.     lowerView = oBrowserSplitView;
  627.  
  628.     [[sender window] disableDisplay];
  629.     [sender adjustSubviews];
  630.  
  631.     // adjust upper(self) view size
  632.     [sender getFrame:&viewFrame];
  633.     [upperView getFrame:&upperFrame];    // upperView is ScrollView
  634.         // and oNewsfolderDockMatrix is a docView of that ScrollView
  635.  
  636.     [oNewsfolderDockMatrix getCellSize:&cellSize];
  637.     [oNewsfolderDockMatrix getIntercell:&intercell];
  638.     [oNewsfolderDockMatrix getEnoughNumRows:&nrows numCols:&ncols 
  639.                         forSize:&(upperFrame.size)];
  640.     upperFrame.size.height = cellSize.height * nrows +
  641.                              intercell.height * (nrows-1);
  642.     [upperView setFrame:&upperFrame];
  643.     
  644.     // compute lower view size
  645.     viewFrame.origin.y = [sender dividerHeight] + upperFrame.size.height;
  646.                         // coord. is flipped in NXSplitView
  647.     viewFrame.size.height -= viewFrame.origin.y;
  648.     [lowerView setFrame:&viewFrame];    
  649.  
  650.     [[sender window] reenableDisplay];
  651.     
  652.     // unregister cell's frame to viewRectList in AcceptWindow
  653.     // so that the clipped cell can not be used as dropped well
  654.     [oNewsfolderDockMatrix getNumRows:&numRows numCols:&numCols];
  655.     if (numCols > ncols) {
  656.     // remove columns
  657.     for (i = (numCols-1); i > (ncols-1); --i) {
  658.         // unregister rect of cell which will be clipped by ScrollView,
  659.         // which is a superview of this class
  660.         for (j = (numRows-1); j >= 0; --j) {
  661.         [oNewsfolderDockMatrix unregisterCellAt:j :i window:nil];
  662.         }
  663.     }
  664.     }
  665.     
  666.     if (numRows > nrows) {
  667.     // remove rows
  668.     for (i = (numRows-1); i > (nrows-1); --i) {
  669.         // unregister rect of cell which will be clipped by ScrollView,
  670.         // which is a superview of this class
  671.         for (j = (numCols-1); j >= 0; --j) {
  672.         [oNewsfolderDockMatrix unregisterCellAt:i :j window:nil];
  673.         }
  674.     }
  675.     }
  676.     
  677.     // reregister the cells in Scroll view
  678.     [oNewsfolderScrollMatrix registerCells];
  679.     
  680.     return self;
  681. }
  682.  
  683. - splitView:sender getMinY:(NXCoord *)minY maxY:(NXCoord *)maxY
  684.                         ofSubviewAt:(int)offset
  685. {
  686.     NXRect    viewFrame;
  687.     int        nrows, ncols;
  688.     id        upperView, lowerView;
  689.     NXSize    cellSize, intercell;
  690.  
  691.     upperView = oNewsfolderDockMatrix;
  692.     lowerView = oBrowserSplitView;
  693.     
  694.     [upperView getCellSize:&cellSize];
  695.     [upperView getIntercell:&intercell];
  696.  
  697.     *minY = 0.0;
  698.     [sender getFrame:&viewFrame];
  699.     viewFrame.size.height -= SCRLLMATRIX_HEIGHT;
  700.     [upperView getEnoughNumRows:&nrows numCols:&ncols 
  701.                         forSize:&(viewFrame.size)];
  702.     nrows -= 1;            // avoid that the upperview size will be 
  703.                     // overflow because of rounding nrows
  704.     if (nrows >= 1) {
  705.     *maxY = cellSize.height * nrows + intercell.height * (nrows -1);
  706.     } else {
  707.     *maxY = 0.0;
  708.     }
  709.     
  710.     return self;
  711. }
  712.  
  713.  
  714. @end
  715.